from flask import Flask
from flask import render_template
from flask import request,flash,g,url_for
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager, login_required, login_user,logout_user,current_user
from forms import LoginForm,EditForm,AddpostForm,RegistryForm,MessageForm,SearchForm
from flask import redirect
from flask_wtf import CSRFProtect
from datetime import datetime
import config
import os
from config import POSTS_PER_PAGE,ALLOWED_EXTENSIONS,UPLOAD_FOLDER,ES_HOST
from os import path
from werkzeug import secure_filename
from flask import send_from_directory
from PIL import Image
from elasticsearch import Elasticsearch

app = Flask(__name__)
app.config.from_object('config')
db = SQLAlchemy(app)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER

# csrf protection
csrf = CSRFProtect()
csrf.init_app(app)


login_manager = LoginManager()
login_manager.session_protection = 'strong'
login_manager.login_view = 'login'
login_manager.init_app(app=app)
import models

lm = LoginManager()
lm.init_app(app)
lm.login_view = 'login'


@app.route('/index')
@app.route('/')
@app.route('/index/<int:page>', methods = ['GET', 'POST'])
#@login_required
def index(page=1,user='youke',user_id=None):
    form_search=SearchForm()
    if g.user.is_authenticated:
        user=g.user
    posts=models.Post.query.join(models.User, models.Post.user_id==models.User.id).add_entity(models.User).paginate(page,POSTS_PER_PAGE, False)
    db.session.remove()
    return render_template("index.html",posts=posts,user=user,form_search=form_search)
@app.route('/login', methods = ['GET', 'POST'])
def login():
    if g.user is not None and g.user.is_authenticated:
       # flash('you have login success!')
        return redirect(url_for('index'))
    form=LoginForm()
    form_search=SearchForm()
    if form.validate_on_submit():
       # flash('you have input success')
        user_name = request.form.get('username', None)
        password = request.form.get('password', None)
        remember_me = request.form.get('remember_me', False)
        #user = models.User(user_name,password)
        user = models.User.query.filter_by(username=user_name).first()
        if user.check_password(password):
            db.session.remove()
            login_user(user)
            return redirect('/index')
    return  render_template("login.html",form=form,form_search=form_search)
@lm.user_loader
def load_user(id):
    #Id=models.User_table.query.filter_by(username=id).first()
    return models.User.query.filter_by(username=id).first()
    db.session.remove()
@app.route("/logout")
@login_required
def logout():
    logout_user()
    db.session.remove()
    return redirect('/login')

@app.route('/user/<username>')
@app.route('/user/<username>/<int:page>')
#@login_required
def user(username,page=1):
    user= models.User.query.filter_by(username = username).first()
    db.session.remove()
    form_search=SearchForm()
    if user == None:
        flash('User ' + username + ' not found.')
        return redirect('/index')
    posts=models.Post.query.filter_by(user_id = user.id).paginate(page, POSTS_PER_PAGE, False)
    db.session.remove()
    return render_template('user.html',
                           user = user,
                           posts = posts,form_search=form_search)
@app.before_request
def before_request():
    g.user = current_user
#    if g.user.is_authenticated:
#        g.user.last_seen = datetime.today()
#        db.session.commit()
#        db.session.remove()
@app.route('/edit', methods=['GET', 'POST'])
@login_required
def edit():
    from models import db
    form = EditForm()
    form_search=SearchForm()
    headimg_path=os.path.join(os.getcwd(),'static')
    if form.validate_on_submit():
        g.user.username = form.username.data
        g.user.about_me = form.about_me.data
        avator =request.files['avator']
        size = (128, 128)
        try:
            im = Image.open(avator)
            im.thumbnail(size)
            fname=secure_filename(avator.filename)
            flag='.' in fname and fname.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS
            if not flag:
                flash ('file wrong type')
                return redirect(url_for('edit'))
            im.save(os.path.join(app.config['UPLOAD_FOLDER'], fname))
            g.user.avator=(fname)
        except:
            pass
        db.session.add(g.user)
        db.session.commit()
        db.session.remove()
        flash ('upload success')
        return redirect(url_for('edit',form_search=form_search))
    else:
        form.username.data = g.user.username
        form.about_me.data = g.user.about_me
    return render_template('edit.html', form=form,form_search=form_search)
@app.route('/addpost', methods=['GET', 'POST'])
@login_required
def addpost():
    from models import db
    form = AddpostForm()
    form_search=SearchForm()
    if form.validate_on_submit():
        title=request.form.get('title')
        body=request.form.get('body')
        summary=request.form.get('summary')
        tag=request.form.get('tag')
        timestamp=datetime.today()
        user_id=g.user.id
        post=models.Post(title,body,timestamp,user_id,summary,tag)
        db.session.add(post)
        db.session.commit()
#        db.session.remove()
        return redirect(url_for('index'))
    return render_template('addpost.html', form=form,form_search=form_search)

@app.errorhandler(404)
def internal_error(error):
    return render_template('404.html'), 404

@app.errorhandler(500)
def internal_error(error):
    db.session.rollback()
    return render_template('500.html'), 500
@app.route('/registry', methods=['GET', 'POST'])
def registry():
    from models import db
    form = RegistryForm()
    form_search=SearchForm()
    if form.validate_on_submit():
        user_name = request.form.get('username', None)
        password = request.form.get('password', None)
        repassword = request.form.get('repassword', None)
        email = request.form.get ('email',None)
        avator=None
        if password == repassword:
            user = models.User(user_name,password,email,avator=None)
            db.session.add(user)
            db.session.commit()
            login_user(user)
            db.session.remove()
            return redirect('/index')
    return  render_template("registry.html",form=form,form_search=form_search)

@app.route('/blog/<id>', methods=['GET', 'POST'])
#@login_required
def blog(id=None):
    form_search=SearchForm()
    user='youke'
    if g.user.is_authenticated:
        user=g.user.username
        #db.session.remove()
    from models import db
    body = models.Post.query.filter_by(id=id).first().body
    title = models.Post.query.filter_by(id=id).first().title
    summary = models.Post.query.filter_by(id=id).first().summary
    try:
        message = models.Message.query.filter_by(post_id=id)
        db.session.remove()
    except:
        return None
    form=MessageForm()
    form.username.data=user
    if form.validate_on_submit():
        post=models.Message()
        post.message=request.form.get('message')
        post.timestamp=datetime.today()
        post.msg_from=user
        post.post_id=id
        db.session.add(post)
        db.session.commit()
        db.session.remove()
    return render_template("blog.html",body=body,title=title,summary=summary,message=message,form=form,id=id,form_search=form_search)

@app.route('/editpost/<title>', methods=['GET', 'POST'])
@app.route('/editpost',methods=['GET','POST'])
@login_required
def editpost(title=None):
        from models import db
        form = AddpostForm()
        form_search=SearchForm()
        post=models.Post.query.filter_by(title=title).first()
        db.session.remove()
        form.title.data=title
        form.body.data=post.body
        form.summary.data=post.summary
        form.tag.data=post.tag
        if form.validate_on_submit():
            post.title=request.form.get('title')
            post.body=request.form.get('body')
            post.summary=request.form.get('summary')
            post.tag=request.form.get('tag')
            post.timestamp=datetime.today()
            db.session.add(post)
            db.session.commit()
            db.session.remove()
            return redirect(url_for('index'))
        return render_template('editpost.html', form=form,post=post,title=title,form_search=form_search)
@app.route('/delpost/<title>', methods=['GET', 'POST'])
@app.route('/delpost',methods=['GET','POST'])
@login_required
def delpost(title=None):
    from models import db
    form_search=SearchForm()
    post=models.Post.query.filter_by(title=title)
    for p in post:
        db.session.delete(p)
        db.session.commit()
    page=1
    form=LoginForm()
    user=g.user
    posts=models.Post.query.filter_by(user_id = user.id)
    titles=posts.paginate(page, POSTS_PER_PAGE, False)
    return render_template('index.html',user=user,
                           posts=posts,
                           titles=titles,
                           form=form,
                           form_search=form_search)
@app.route('/uploads/<filename>')
def uploaded_file(filename):
    return send_from_directory(app.config['UPLOAD_FOLDER'],
                               filename)
@app.route('/tag/<tag_name>')
def tag(tag_name,page=1,user='youke'):
    form_search=SearchForm()
    posts=models.Post.query.filter_by(tag=tag_name).join(models.User, models.Post.user_id==models.User.id).add_entity(models.User).paginate(page,POSTS_PER_PAGE, False)
    db.session.remove()
    return render_template('tag.html',posts=posts,form_search=form_search)
def get_username(user_id):
    username=models.User.query.filter_by(id=user_id).first().username
    db.session.remove()
    return username
@app.route('/search',methods=['GET','POST'])
def search():
    try:
        query=request.form.get('search')
        return redirect(url_for('search_results', query = query))
    except:
        return redirect(url_for('search'))
@app.route('/search_results/<query>')
def search_results(query):
    es = Elasticsearch(ES_HOST)
    form_search=SearchForm()
    #result = models.Post.query.whoosh_search(query).all()
    result = es.search(index="microblog", body={'query':{'match':{'body':query}}})
    #db.session.remove()
    return render_template('search_result.html',
                       query = query,
                       result = result,
                       form_search=form_search)
@app.teardown_request
def dbsession_clean(exception=None):
    try:
        db.session.remove()
    finally:
        pass
if __name__ == '__main__':
    app.debug = True
    app.run(host="0.0.0.0")
